﻿using FDSQLAssistant.Busi;
using FDSQLAssistant.Extensions;
using FDSQLAssistant.Models;
using FDSQLAssistant.Repositories;
using FDSQLAssistant.Services;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;

namespace FDSQLAssistant
{
    class Program
    {
        static void Main(string[] args)
        {
            var services = Init();

            //var g = provider.GetService<IGenerator>();
            //Console.WriteLine(g.InsertSql("Users"));

            var runArgsResult = DealRunArgs(args);//DealRunArgs(new[] { "-t:Rom_ApkClientShouldExcept", "/c:Id=2", "--n:1", "--d:languo" });//
            if (runArgsResult != null && runArgsResult.IsHelp)
            {
                ShowHelp();
                return;
            }

            InputMenu im = runArgsResult;
        AGAIN:
            if (im?.Choose == 5)
            {
                goto End;
            }
            im = ShowMenu(im, services);
            if (im.Choose == 0)
            {
                1.Output("Please choose the business number.");
                goto AGAIN;
            }
            if (im.Choose == 5)
            {
                goto End;
            }

            if (im.TableName.IsNullOrEmpty())
            {
                1.Output("Please input the table name to deal the business.");
                goto AGAIN;
            }

            var provider = services.BuildServiceProvider();
            FDContext.Default.SetProvider(provider);
            var buz = provider.GetService<IBusinessManager>();
            var sql = string.Empty;
            TryDo(() =>
            {
                sql = buz.GetSql(im.TableName, im.Condition, im.BuzType);
            }, "生成SQL失败");

            if (sql.IsNullOrEmpty())
            {
                1.Output("Nothing for the specified business.");
            }
            else
            {
                1.Output("Result for the business:");
                1.Output(sql);
            }

            1.Output("Again?(Y/n):");
            var again = 1.ReadLine();
            if (again.IsNullOrEmpty() || again.Equals("yes", StringComparison.OrdinalIgnoreCase) ||
                again.Equals("y", StringComparison.OrdinalIgnoreCase))
            {
                im = null;
                goto AGAIN;
            }
        End:
            1.Output("Byte!");
            Console.Read();
        }

        private static void TryDo(Action action, string errMsg)
        {
            try
            {
                action?.Invoke();
            }
            catch (Exception e)
            {
                1.Output($"{(errMsg.IsNullOrEmpty() ? "" : $"{errMsg}: ")}{e.Message}");
            }
        }

        private static void ShowHelp()
        {
            1.Output("==================================");
            1.Output("The command arguemnt like -h(--h,/h,-help,--help,/help) for help.");
            1.Output("The command arguemnt like -n(--n,/n) for the number to deal the business.And like under:");
            1.Output("Input the number for dealing the business:");
            1.Output("\t1.Generate Insert SQL");
            1.Output("\t2.Generate Update SQL");
            1.Output("\t3.Generate Select SQL");
            1.Output("\t4.Generate Delete SQL");
            1.Output("\t5.Exit");
            1.Output("The command arguemnt like -c(--c,/c,/condition,--condition,-condition) for the condition to the business.");
            1.Output("The command arguemnt like -t(--t,/t,/tablename,--tablename,-tablename) for the tablename to the business.");
            1.Output("The command arguemnt like -d(--d,/d,/dbname,--dbname,-dbname) for the data base connection string name to the business.");
            1.Output("==================================");
        }

        private static RunArgument DealRunArgs(string[] args)
        {
            if (args.Length == 0)
                return null;
            if (args.ContainsIgnoreCase("-h", "/h", "/help", "-help", "--help", "--h"))
            {
                return new RunArgument { IsHelp = true };
            }

            var ra = new RunArgument();
            foreach (var arg in args)
            {
                var items = arg.Split(new[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                if (items.Length < 2)
                    continue;
                if (items[0].ContainsIgnoreCaseAny("-n", "--n", "/n"))
                {
                    int.TryParse(items[1], out int n);
                    ra.Choose = n;
                }
                else if (items[0].ContainsIgnoreCaseAny("-c", "--c", "/c", "-condition", "--condition", "/condition"))
                {
                    ra.Condition = items[1];
                }
                else if (items[0].ContainsIgnoreCaseAny("-t", "--t", "/t", "-tableName", "--tablename", "/tablename"))
                {
                    ra.TableName = items[1];
                }
                else if (items[0].ContainsIgnoreCaseAny("-d", "--d", "/d", "-dbname", "--dbname", "/dbname"))
                {
                    ra.ConnStringName = items[1];
                }
            }

            return ra;
        }

        static InputMenu ShowMenu(InputMenu inputMenu, IServiceCollection services)
        {
            int choose = inputMenu?.Choose ?? 0;
            string tableName = inputMenu?.TableName;
            string condition = inputMenu?.Condition;
            string connStringName = inputMenu?.ConnStringName;
            if (inputMenu == null || inputMenu.Choose == 0)
            {
                1.Output("==================================");
                1.Output("Input the number for dealing the business:");
                1.Output("\t1.Generate Insert SQL");
                1.Output("\t2.Generate Update SQL");
                1.Output("\t3.Generate Select SQL");
                1.Output("\t4.Generate Delete SQL");
                1.Output("\t5.Exit");
                int.TryParse(1.ReadLine(), out choose);
            }

            if (choose == 5)
            {
                return new InputMenu { Choose = 5 };
            }

            if (inputMenu == null || inputMenu.TableName.IsNullOrEmpty())
            {
                1.Output("Input the table name:", false);
                tableName = 1.ReadLine();
            }

            if (condition.IsNullOrEmpty())
            {
                1.Output("Input the condition for the business:", false);
                condition = 1.ReadLine();
            }

            if (connStringName.IsNullOrEmpty())
            {
                var conns = FDContext.Default.SysConfig.Connections;
                1.Output("==================================");
                for (var i = 0; i < conns.Count; ++i)
                {
                    1.Output($"{i + 1}.{conns[i].Name}");
                }

                1.Output("Input the connection string name:", false);
                var numName = 1.ReadLine();
                if (int.TryParse(numName, out int n) && (n > 0 && n <= conns.Count))
                {
                    connStringName = conns[n - 1].Name;
                }
            }
            if (!connStringName.IsNullOrEmpty())
            {
                var config =
                    FDContext.Default.SysConfig.Connections.FirstOrDefault(a =>
                        a.Name.ContainsIgnoreCase(connStringName));
                if (config == null)
                {
                    config = FDContext.Default.SysConfig.Connections.First();
                }

                var confService = services.FirstOrDefault(a => a.ServiceType == typeof(Config));
                if (confService != null)
                {
                    services.Remove(confService);
                }

                services.AddSingleton(config);
            }

            1.Output("==================================");

            return new InputMenu
            {
                Choose = choose,
                TableName = tableName,
                Condition = condition
            };
        }


        static IServiceCollection Init()
        {
            var services = new ServiceCollection();
            services.AddSingleton<IGenerator, ModelGenerator>();
            services.AddTransient<ICommonRepository, CommonRepository>();
            services.AddTransient<ICommonRepository, MySqlCommonRepository>();
            services.AddScoped<IBusinessManager, BusinessManager>();
            services.AddSingleton(FDContext.Default.SysConfig.Connections.First());
            return services;
        }
    }
}
